package cn.buk.tms.dao;

import cn.buk.tms.factory.OperationLogFactory;
import cn.buk.tms.entity.bill.BillFlightTicket;
import cn.buk.tms.entity.bill.BillInfo;
import cn.buk.tms.entity.bill.BillVasOrder;
import cn.buk.tms.entity.bill.BillVasOrderPassenger;
import cn.buk.tms.entity.misc.OperationLog;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import jakarta.transaction.Transactional;

import static cn.buk.tms.common.constant.TmsOrderConstant.BILL_TYPE_FLIGHT;
import static cn.buk.tms.common.constant.TmsOrderConstant.BILL_TYPE_VAS;

/**
 * @author yfdai
 * 创建于2021-01-28 18:20
 */
@Component
@Transactional
public class BillSplitDaoImpl extends AbstractBillDao implements BillSplitDao {


  @Override
  public int splitFlightBill(final int enterpriseId, final String username, final int billId, final int ticketId,
                             final String newBillNo) {
    BillInfo billInfo = doGetBillInfo(billId, true);
    if (billInfo == null || billInfo.getEnterpriseId() != enterpriseId
            || !BILL_TYPE_FLIGHT.equalsIgnoreCase(billInfo.getBillType())) {
      throw new RuntimeException("BillInfo cannot be split.");
    }

    if (billInfo.getTickets().size() < 2) {
      throw new RuntimeException("BillInfo cannot be split.");
    }

    BillFlightTicket ticketSplitted = null;

    for(BillFlightTicket ticket: billInfo.getTickets()) {
      if (ticket.getId() == ticketId) {
        ticketSplitted = ticket;
        break;
      }
    }
    if (ticketSplitted == null) {
      throw new RuntimeException("Ticket(splitted from BillInfo) cannot be found.");
    }

    BillInfo newBillInfo = new BillInfo();
    BeanUtils.copyProperties(billInfo, newBillInfo);

    //new billInfo
    newBillInfo.setId(0);
    newBillInfo.setBillSum(ticketSplitted.getAccountRecv());
    newBillInfo.setCost(ticketSplitted.getCost());
    newBillInfo.setProfit(ticketSplitted.getProfit());
    newBillInfo.setTicketCount(1);
    newBillInfo.setBillNum(newBillNo);
    ticketSplitted.setBillNum(newBillNo);
    em.merge(ticketSplitted);

    em.persist(newBillInfo);
    OperationLog log = OperationLogFactory.createBillOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(newBillInfo.getId());
    log.setOperator(username);
    log.setContent("从账单(" + billInfo.getBillNum() + ")分离机票(" + ticketSplitted.getPassengerName() + ", " + ticketSplitted.getTicketNo() + ")生成账单");
    em.persist(log);

    //original billInfo
    double oldBillSum = billInfo.getBillSum();
    double oldCost = billInfo.getCost();
    double oldProfit = billInfo.getProfit();
    billInfo.setBillSum(billInfo.getBillSum()-ticketSplitted.getAccountRecv());
    billInfo.setCost(billInfo.getCost()-ticketSplitted.getCost());
    billInfo.setProfit(billInfo.getProfit()-ticketSplitted.getProfit());
    billInfo.setTicketCount(billInfo.getTicketCount()-1);
    em.merge(billInfo);

    log = OperationLogFactory.createBillOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(billInfo.getId());
    log.setOperator(username);
    log.setContent("将机票(" + ticketSplitted.getPassengerName() + ", " + ticketSplitted.getTicketNo() + ")分离到账单(" + newBillNo + ")");
    em.persist(log);

    log = OperationLogFactory.createBillOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(billInfo.getId());
    log.setOperator(username);
    log.setContent("账单金额：" + oldBillSum + "->" + billInfo.getBillSum() + "; " +
            "成本：" + oldCost + "->" + billInfo.getCost() + "; " +
            "利润：" + oldProfit + "->" + billInfo.getProfit());
    em.persist(log);

    return 1;
  }


  @Override
  public int splitVasBill(final int enterpriseId, final String username, final int billId, final int orderId,
                          final int psgId, final String newBillNo) {
    BillInfo billInfo = doGetBillInfo(billId, true);
    if (billInfo == null || billInfo.getEnterpriseId() != enterpriseId
            || !BILL_TYPE_VAS.equalsIgnoreCase(billInfo.getBillType())) {
      throw new RuntimeException("BillInfo cannot be split.");
    }

    if (billInfo.getVasOrders().size() != 1) {
      throw new RuntimeException("BillInfo cannot be split.");
    }

    BillVasOrder billVasOrder = billInfo.getVasOrders().get(0);
    if (billVasOrder.getPassengers().size() < 2
            || billVasOrder.getPsgCount() != billVasOrder.getPassengers().size()
            || billVasOrder.getPsgCount() != billVasOrder.getCount()) {
      throw new RuntimeException("BillInfo cannot be split.");
    }

    BillVasOrderPassenger psgSplitted = null;
    String changedPsgName = null;

    for(BillVasOrderPassenger psg: billVasOrder.getPassengers()) {
      if (psg.getId() == psgId) {
        psgSplitted = psg;
      } else if (changedPsgName == null) {
        changedPsgName = psg.getName();
      } else {
        changedPsgName += "; " + psg.getName();
      }
    }
    if (psgSplitted == null) {
      throw new RuntimeException("Passenger(splitted from BillInfo) cannot be found.");
    }

    //new billInfo
    BillInfo newBillInfo = new BillInfo();
    BeanUtils.copyProperties(billInfo, newBillInfo);
    newBillInfo.setId(0);


    final double newTotal = billVasOrder.getTotal() / billVasOrder.getCount();
    final double newCost = billVasOrder.getCost() / billVasOrder.getCount();
    final double newProfit = billVasOrder.getProfit() / billVasOrder.getCount();

    newBillInfo.setBillSum(newTotal);
    newBillInfo.setCost(newCost);
    newBillInfo.setProfit(newProfit);
    newBillInfo.setBillNum(newBillNo);
    em.persist(newBillInfo);

    OperationLog log = OperationLogFactory.createBillOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(newBillInfo.getId());
    log.setOperator(username);
    log.setContent("从账单(" + billInfo.getBillNum() + ")分离(" + psgSplitted.getName() + ")生成账单");
    em.persist(log);

    BillVasOrder newBillVasOrder = new BillVasOrder();
    BeanUtils.copyProperties(billVasOrder, newBillVasOrder);
    newBillVasOrder.setId(0);
    newBillVasOrder.setPassengerName(psgSplitted.getName());
    newBillVasOrder.setPsgCount(1);
    newBillVasOrder.setCount(1);
    newBillVasOrder.setBillNum(newBillNo);
    newBillVasOrder.setTotal(newTotal);
    newBillVasOrder.setCost(newCost);
    newBillVasOrder.setProfit(newProfit);
    em.persist(newBillVasOrder);

    psgSplitted.setOrder(newBillVasOrder);
    em.merge(psgSplitted);

    //original billInfo
    double oldBillSum = billInfo.getBillSum();
    double oldCost = billInfo.getCost();
    double oldProfit = billInfo.getProfit();
    billInfo.setBillSum(billInfo.getBillSum()-newTotal);
    billInfo.setCost(billInfo.getCost()-newCost);
    billInfo.setProfit(billInfo.getProfit()-newProfit);
    em.merge(billInfo);

    log = OperationLogFactory.createBillOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(billInfo.getId());
    log.setOperator(username);
    log.setContent("将(" + psgSplitted.getName() + ")分离到账单(" + newBillNo + ")");
    em.persist(log);

    log = OperationLogFactory.createBillOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(billInfo.getId());
    log.setOperator(username);
    log.setContent("账单金额：" + oldBillSum + "->" + billInfo.getBillSum() + "; " +
            "成本：" + oldCost + "->" + billInfo.getCost() + "; " +
            "利润：" + oldProfit + "->" + billInfo.getProfit());
    em.persist(log);

    billVasOrder.setPassengerName(changedPsgName);
    billVasOrder.setPsgCount(billVasOrder.getPsgCount() - 1);
    billVasOrder.setCount(billVasOrder.getCount() - 1);
    billVasOrder.setTotal(billVasOrder.getTotal() - newTotal);
    billVasOrder.setCost(billVasOrder.getCost() - newCost);
    billVasOrder.setProfit(billVasOrder.getProfit() - newProfit);

    return 1;
  }
}
